﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Drawing.Imaging;
using System.Threading;
using System.Windows.Forms;
using BTKinect.DataType;
using OpenNI;
using OX.Copyable;

namespace BTKinect
{
    public partial class frmMain : Form
    {

        #region MEMBERS
        private readonly string SAMPLE_XML_FILE = @"C:\Program Files\OpenNI\Data\SamplesConfig.xml";

        private Context context;
        private ScriptNode scriptNode;
        private DepthGenerator depth;
        private UserGenerator userGenerator;
        private SkeletonCapability skeletonCapbility;
        private PoseDetectionCapability poseDetectionCapability;
        private Dictionary<int, Dictionary<SkeletonJoint, SkeletonJointPosition>> joints;
        private Dictionary<SkeletonJoint, SkeletonJointPosition> dict;
        private Dictionary<SkeletonJoint, KinectPoint3D> dictForSaving;
        private Thread readerThread;
        private Bitmap bitmap;

        private int[] histogram;
        private string calibPose;
        private string strTxtMarker = "Marker!";
        private bool blMarkerPressed = false;
        private bool shouldDrawPixels = true;
        private bool shouldDrawBackground = true;
        private bool shouldPrintID = true;
        private bool shouldPrintState = true;
        private bool shouldDrawSkeleton = true;
        private bool shouldRun;
        private bool blMeasuring = false;
        private bool blUseMarker = true;
        private bool blFoundKinect = false;

        //private Dictionary<SkeletonJoint, SkeletonJointPosition> dictThread; //first temp dictionary
        private KinectData kd; //object
        private KinectBasicCalculations kbc;
        private KinectReadData krd;
        private KinectExportData ked;
        private Type type = typeof(Dictionary<SkeletonJoint, SkeletonJointPosition>);
        private Help hlp = new Help();
        private MuisMeetModus mmd = new MuisMeetModus();


        #endregion

        #region CONSTRUCTOR
        public frmMain()
        {
            InitializeComponent();
            setupAll();
        }
        #endregion

        #region GENERAL FUNCTIONS
        private void setupAll()
        {
            //reset functions
            if (readerThread != null)
            {
                this.shouldRun = false;
                readerThread.Join();
            }

            //setup functions
            try
            {
                this.context = Context.CreateFromXmlFile(SAMPLE_XML_FILE, out scriptNode);
                this.depth = context.FindExistingNode(NodeType.Depth) as DepthGenerator;
                if (this.depth != null)
                    blFoundKinect = true;
            }
            catch (Exception)
            {
                MessageBox.Show("De Kinect is niet gevonden. Als de Kinect (opnieuw) is aangesloten ga dan naar het menu 'Optimaliseer' en druk op reset", "Mededeling", MessageBoxButtons.OK, MessageBoxIcon.Information);
            }


            if (blFoundKinect)
            {
                this.userGenerator = new UserGenerator(this.context);
                this.skeletonCapbility = this.userGenerator.SkeletonCapability;
                this.poseDetectionCapability = this.userGenerator.PoseDetectionCapability;
                this.calibPose = this.skeletonCapbility.CalibrationPose;

                //events
                this.userGenerator.NewUser += userGenerator_NewUser;
                this.userGenerator.LostUser += userGenerator_LostUser;
                this.poseDetectionCapability.PoseDetected += poseDetectionCapability_PoseDetected;
                this.skeletonCapbility.CalibrationComplete += skeletonCapbility_CalibrationComplete;

                this.skeletonCapbility.SetSkeletonProfile(SkeletonProfile.All);
                this.joints = new Dictionary<int, Dictionary<SkeletonJoint, SkeletonJointPosition>>();
                this.userGenerator.StartGenerating();

                //drawing
                this.histogram = new int[this.depth.DeviceMaxDepth];
                MapOutputMode mapMode = this.depth.MapOutputMode;
                int screenWidth = System.Windows.Forms.Screen.PrimaryScreen.Bounds.Width;
                int screenHeight = System.Windows.Forms.Screen.PrimaryScreen.Bounds.Height;

                this.bitmap = new Bitmap((int)mapMode.XRes, (int)mapMode.YRes/*, System.Drawing.Imaging.PixelFormat.Format24bppRgb*/);
                this.shouldRun = true;

                this.readerThread = new Thread(new ThreadStart(ReaderThread));
                this.readerThread.Start();
                updateSmoothFactor(0.0F);

                kd = new KinectData(1800);
                toolStripProgressBar1.Value = 0;
            }
            else
            {
                metenToolStripMenuItem.Enabled = false;
            }

            toolStripStatusLabel1.Text = "";
            toolStripStatusLabel2.Text = "";
            gebruikRealworldCoordinatenToolStripMenuItem.Checked = true;
            kbc = new KinectBasicCalculations(this.depth);
            UpdateMenu();
        }


        private void pnlView_MouseClick(object sender, MouseEventArgs e)
        {
            if (muisMeetmodusToolStripMenuItem.Checked)
            {
                if (e.Button == MouseButtons.Left)
                    blMarkerPressed = true;
                else
                {
                    if (blMeasuring)
                        stopMeting();
                    else
                        startMeting();
                }
            }
        }
        #endregion

        #region SKELETONHANDLING
        #region General skeleton functions
        void skeletonCapbility_CalibrationComplete(object sender, CalibrationProgressEventArgs e)
        {
            if (e.Status == CalibrationStatus.OK)
            {
                this.skeletonCapbility.StartTracking(e.ID);
                this.joints.Add(e.ID, new Dictionary<SkeletonJoint, SkeletonJointPosition>());
                this.skeletonCapbility.SetSmoothing(0);
            }
            else
            {
                this.poseDetectionCapability.StartPoseDetection(calibPose, e.ID);
            }
        }
        void poseDetectionCapability_PoseDetected(object sender, PoseDetectedEventArgs e)
        {
            this.poseDetectionCapability.StopPoseDetection(e.ID);
            this.skeletonCapbility.RequestCalibration(e.ID, true);
        }
        void userGenerator_NewUser(object sender, NewUserEventArgs e)
        {
            this.poseDetectionCapability.StartPoseDetection(this.calibPose, e.ID);
        }
        void userGenerator_LostUser(object sender, UserLostEventArgs e)
        {
            this.joints.Remove(e.ID);
        }

        protected override void OnPaint(PaintEventArgs e)
        {
            if (blFoundKinect)
            {
                base.OnPaint(e);

                lock (this)
                {
                    e.Graphics.DrawImage(this.bitmap,
                        this.pnlView.Location.X,
                        this.pnlView.Location.Y,
                        this.pnlView.Size.Width,
                        this.pnlView.Size.Height);
                }
            }
        }
        protected override void OnPaintBackground(PaintEventArgs pevent)
        {
            //Don't allow the background to paint
        }
        protected override void OnClosing(CancelEventArgs e)
        {
            if (blFoundKinect)
            {
                this.shouldRun = false;
                this.readerThread.Join();
            }
            base.OnClosing(e);
        }
        protected override void OnKeyPress(KeyPressEventArgs e)
        {
            if (e.KeyChar == 27)
            {
                Close();
            }
            switch (e.KeyChar)
            {
                case (char)27:
                    break;
                case 'b':
                    this.shouldDrawBackground = !this.shouldDrawBackground;
                    break;
                case 'x':
                    this.shouldDrawPixels = !this.shouldDrawPixels;
                    break;
                case 's':
                    this.shouldDrawSkeleton = !this.shouldDrawSkeleton;
                    break;
                case 'i':
                    this.shouldPrintID = !this.shouldPrintID;
                    break;
                case 'l':
                    this.shouldPrintState = !this.shouldPrintState;
                    break;
                case 'm':
                    markerPressed();
                    break;
            }
            base.OnKeyPress(e);
        }

        private unsafe void CalcHist(DepthMetaData depthMD)
        {
            /// reset
            ///for (int i = 0; i < this.histogram.Length; ++i)
            ///    this.histogram[i] = 0;
            Array.Clear(this.histogram, 0, this.histogram.Length);

            ///get pointer to depth informatie
            ushort* pDepth = (ushort*)depthMD.DepthMapPtr.ToPointer();

            ///put every pixel in an histogram
            int points = 0;
            for (int y = 0; y < depthMD.YRes; ++y)
            {
                for (int x = 0; x < depthMD.XRes; ++x, ++pDepth)
                {
                    ushort depthVal = *pDepth;
                    if (depthVal != 0)
                    {
                        this.histogram[depthVal]++;
                        points++;
                    }
                }
            }
            ///presumption: shift one position to left because first element
            ///isn't used
            for (int i = 1; i < this.histogram.Length; i++)
            {
                this.histogram[i] += this.histogram[i - 1];
            }

            ///presumption: normalizing depth data 
            if (points > 0)
            {
                for (int i = 1; i < this.histogram.Length; i++)
                {
                    this.histogram[i] = (int)(256 * (1.0f - (this.histogram[i] / (float)points)));
                }
            }
        }
        private Color[] colors = { Color.OrangeRed };
        private Color[] anticolors = { Color.White };
        private int ncolors = 1;
        private void GetJoint(int user, SkeletonJoint joint)
        {
            SkeletonJointPosition pos = this.skeletonCapbility.GetSkeletonJointPosition(user, joint);
            if (pos.Position.Z == 0)
            {
                pos.Confidence = 0;
            }
            else
            {
                pos.Position = this.depth.ConvertRealWorldToProjective(pos.Position);
            }
            this.joints[user][joint] = pos;
        }
        private void GetJoints(int user)
        {
            GetJoint(user, SkeletonJoint.Head);
            GetJoint(user, SkeletonJoint.Neck);

            GetJoint(user, SkeletonJoint.LeftShoulder);
            GetJoint(user, SkeletonJoint.LeftElbow);
            GetJoint(user, SkeletonJoint.LeftHand);

            GetJoint(user, SkeletonJoint.RightShoulder);
            GetJoint(user, SkeletonJoint.RightElbow);
            GetJoint(user, SkeletonJoint.RightHand);

            GetJoint(user, SkeletonJoint.Torso);

            GetJoint(user, SkeletonJoint.LeftHip);
            GetJoint(user, SkeletonJoint.LeftKnee);
            GetJoint(user, SkeletonJoint.LeftFoot);

            GetJoint(user, SkeletonJoint.RightHip);
            GetJoint(user, SkeletonJoint.RightKnee);
            GetJoint(user, SkeletonJoint.RightFoot);
        }
        #endregion

        #region skeleton draw functions
        private void DrawLine(Graphics g, Color color, Dictionary<SkeletonJoint, SkeletonJointPosition>
            dict, SkeletonJoint joint1, SkeletonJoint joint2, string nameJoint)
        {
            KinectPoint3D pos1 = dict[joint1].Position;
            KinectPoint3D pos2 = dict[joint2].Position;
            KinectPoint3D pos1Real = kbc.CalculateRealValues(pos1);
            KinectPoint3D pos2Real = kbc.CalculateRealValues(pos2);

            //if the values are not valid 
            if (dict[joint1].Confidence == 0 || dict[joint2].Confidence == 0)
                return;

            g.DrawLine(new Pen(color, 5),
                        new Point((int)pos1.X, (int)pos1.Y),
                        new Point((int)pos2.X, (int)pos2.Y));

            //draw label show realworld lengths
            if (nameJoint == "" && laatLengtesZienmmToolStripMenuItem.Checked && gebruikRealworldCoordinatenToolStripMenuItem.Checked)
                g.DrawString(Math.Round(pos1Real.Distance(pos2Real), 0).ToString(),
                    new Font("Arial", 14, FontStyle.Bold), new SolidBrush(Color.GreenYellow), (float)(pos1.X + pos2.X) / 2, (float)(pos1.Y + pos2.Y) / 2);
            //draw label show projective lengths
            if (nameJoint == "" && laatLengtesZienmmToolStripMenuItem.Checked && !gebruikRealworldCoordinatenToolStripMenuItem.Checked)
                g.DrawString(Math.Round(pos1.Distance(pos2), 0).ToString(),
                    new Font("Arial", 14, FontStyle.Bold), new SolidBrush(Color.GreenYellow), (float)(pos1.X + pos2.X) / 2, (float)(pos1.Y + pos2.Y) / 2);

        }
        private void DrawAngles(Graphics g, Color color, Dictionary<SkeletonJoint, SkeletonJointPosition>
            dict, SkeletonJoint joint1, SkeletonJoint jointCenter, SkeletonJoint joint2)
        {
            KinectPoint3D pos1 = dict[joint1].Position;
            KinectPoint3D pos2 = dict[jointCenter].Position;
            KinectPoint3D pos3 = dict[joint2].Position;
            KinectPoint3D pos1real = kbc.CalculateRealValues(pos1);
            KinectPoint3D pos2real = kbc.CalculateRealValues(pos2);
            KinectPoint3D pos3real = kbc.CalculateRealValues(pos3);

            //draw label show angles calculated from realworld coordinates
            if (gebruikRealworldCoordinatenToolStripMenuItem.Checked)
                g.DrawString(Math.Round(kbc.CalculateAngle(pos1real, pos2real, pos3real)).ToString()
                    + "°", new Font("Arial", 15, FontStyle.Bold), new SolidBrush(Color.GreenYellow), (float)pos2.X, (float)pos2.Y);
            else //draw label show angles calculated from projective coordinates
                g.DrawString(Math.Round(kbc.CalculateAngle(pos1, pos2, pos3)).ToString()
                    + "°", new Font("Arial", 15, FontStyle.Bold), new SolidBrush(Color.GreenYellow), (float)pos2.X, (float)pos2.Y);
        }
        private void DrawRawValues(Graphics g, Color color, Dictionary<SkeletonJoint, SkeletonJointPosition> dict, SkeletonJoint jointToDraw)
        {
            KinectPoint3D point = null;
            if (gebruikRealworldCoordinatenToolStripMenuItem.Checked)
                point = kbc.CalculateRealValues(dict[jointToDraw].Position);
            else
                point = dict[jointToDraw].Position;

            string temp = "Linkerhand: " + Math.Round(point.X, 0).ToString() + ", " + Math.Round(point.Y, 0).ToString() + ", " +
                Math.Round(point.Z, 0).ToString();

            //draw label show angles 
            g.DrawString(temp, new Font("Arial", 16), new SolidBrush(Color.GreenYellow), 10, 10);
        }
        private void DrawSkeleton(Graphics g, Color color, int user)
        {
            GetJoints(user);
            dict = new Dictionary<SkeletonJoint, SkeletonJointPosition>(); //refresh memory
            dict = this.joints[user];

            if (gebruikRealworldCoordinatenToolStripMenuItem.Checked)
                dictForSaving = kbc.CalculateRealValuesDictionary(dict);

            //Save data by making a new copy 
            if (blMeasuring)
            {
                bgwDataHandling.RunWorkerAsync();
                toolStripStatusLabel1.Text = "De meting is gestart";
                //toolStripStatusLabel2.Text = ""; cross-thread error
            }

            DrawLine(g, color, dict, SkeletonJoint.Head, SkeletonJoint.Neck, "Gebruiker");
            DrawLine(g, color, dict, SkeletonJoint.LeftShoulder, SkeletonJoint.Torso, "");
            DrawLine(g, color, dict, SkeletonJoint.RightShoulder, SkeletonJoint.Torso, "");
            DrawLine(g, color, dict, SkeletonJoint.Neck, SkeletonJoint.LeftShoulder, "");
            DrawLine(g, color, dict, SkeletonJoint.LeftShoulder, SkeletonJoint.LeftElbow, "");
            DrawLine(g, color, dict, SkeletonJoint.LeftElbow, SkeletonJoint.LeftHand, "");
            DrawLine(g, color, dict, SkeletonJoint.Neck, SkeletonJoint.RightShoulder, "");
            DrawLine(g, color, dict, SkeletonJoint.RightShoulder, SkeletonJoint.RightElbow, "");
            DrawLine(g, color, dict, SkeletonJoint.RightElbow, SkeletonJoint.RightHand, "");
            DrawLine(g, color, dict, SkeletonJoint.LeftHip, SkeletonJoint.Torso, "");
            DrawLine(g, color, dict, SkeletonJoint.RightHip, SkeletonJoint.Torso, "");
            DrawLine(g, color, dict, SkeletonJoint.LeftHip, SkeletonJoint.RightHip, "");
            DrawLine(g, color, dict, SkeletonJoint.LeftHip, SkeletonJoint.LeftKnee, "");
            DrawLine(g, color, dict, SkeletonJoint.LeftKnee, SkeletonJoint.LeftFoot, "");
            DrawLine(g, color, dict, SkeletonJoint.RightHip, SkeletonJoint.RightKnee, "");
            DrawLine(g, color, dict, SkeletonJoint.RightKnee, SkeletonJoint.RightFoot, "");

            //Draw angles
            if (laatHoekenZiendegToolStripMenuItem.Checked)
            {
                DrawAngles(g, color, dict, SkeletonJoint.RightShoulder, SkeletonJoint.RightElbow, SkeletonJoint.RightHand);
                DrawAngles(g, color, dict, SkeletonJoint.LeftShoulder, SkeletonJoint.LeftElbow, SkeletonJoint.LeftHand);
                DrawAngles(g, color, dict, SkeletonJoint.RightHip, SkeletonJoint.RightKnee, SkeletonJoint.RightFoot);
                DrawAngles(g, color, dict, SkeletonJoint.LeftHip, SkeletonJoint.LeftKnee, SkeletonJoint.LeftFoot);
                DrawAngles(g, color, dict, SkeletonJoint.LeftShoulder, SkeletonJoint.RightShoulder, SkeletonJoint.RightElbow);
                DrawAngles(g, color, dict, SkeletonJoint.RightShoulder, SkeletonJoint.LeftShoulder, SkeletonJoint.LeftElbow);
            }

            //Draw coordinates hand
            if (LaatCoordinatenHandenZien.Checked)
            {
                KinectPoint3D point = kbc.CalculateRealValues(dict[SkeletonJoint.RightHand].Position);
                string str = "X:" + Math.Round(point.X).ToString() + " Y:" + Math.Round(point.Y).ToString()  + " Z:" + Math.Round(point.Z).ToString();
                g.DrawString(str, new Font("Arial", 15, FontStyle.Bold), new SolidBrush(Color.GreenYellow), dict[SkeletonJoint.RightHand].Position.X, dict[SkeletonJoint.RightHand].Position.Y);
                point = kbc.CalculateRealValues(dict[SkeletonJoint.LeftHand].Position);
                str = "X:" + Math.Round(point.X).ToString() + " Y:" + Math.Round(point.Y).ToString()  + " Z:"+ Math.Round(point.Z).ToString();
                g.DrawString(str, new Font("Arial", 15, FontStyle.Bold), new SolidBrush(Color.GreenYellow), dict[SkeletonJoint.LeftHand].Position.X, dict[SkeletonJoint.LeftHand].Position.Y);

            }
        }
        #endregion
        #endregion

        #region READERTHREAD
        private unsafe void ReaderThread() //has to be unsafe in order to use pointers and fixed size buffers
        {
            DepthMetaData depthMD = new DepthMetaData();
            while (this.shouldRun)
            {
                try
                {
                    this.context.WaitOneUpdateAll(this.depth); //this function will give error every now and then
                }
                catch (Exception)
                {
                    try
                    {
                        Thread.Sleep(10); //sleep and try again
                        this.context.WaitOneUpdateAll(this.depth);
                    }
                    catch (Exception e)
                    {
                        MessageBox.Show(e.Message, "Foutmelding!", MessageBoxButtons.OK, MessageBoxIcon.Error);
                    }
                }

                this.depth.GetMetaData(depthMD);
                CalcHist(depthMD);

                lock (this)
                {
                    Rectangle rect = new Rectangle(0, 0, this.bitmap.Width, this.bitmap.Height);
                    BitmapData data = this.bitmap.LockBits(rect, ImageLockMode.WriteOnly, System.Drawing.Imaging.PixelFormat.Format24bppRgb);

                    if (this.shouldDrawPixels)
                    {
                        ushort* pDepth = (ushort*)this.depth.DepthMapPtr.ToPointer();
                        ushort* pLabels = (ushort*)this.userGenerator.GetUserPixels(0).LabelMapPtr.ToPointer();

                        // set pixels
                        for (int y = 0; y < depthMD.YRes; ++y)
                        {
                            byte* pDest = (byte*)data.Scan0.ToPointer() + y * data.Stride;
                            for (int x = 0; x < depthMD.XRes; ++x, ++pDepth, ++pLabels, pDest += 3)
                            {
                                pDest[0] = pDest[1] = pDest[2] = 0;

                                ushort label = *pLabels;
                                if (this.shouldDrawBackground || *pLabels != 0)
                                {
                                    Color labelColor = Color.White;
                                    if (label != 0)
                                    {
                                        labelColor = colors[label % ncolors];
                                    }

                                    byte pixel = (byte)this.histogram[*pDepth];
                                    pDest[0] = (byte)(pixel * (labelColor.B / 256.0));
                                    pDest[1] = (byte)(pixel * (labelColor.G / 256.0));
                                    pDest[2] = (byte)(pixel * (labelColor.R / 256.0));
                                }
                            }
                        }
                    }
                    this.bitmap.UnlockBits(data);

                    Graphics g = Graphics.FromImage(this.bitmap);
                    int[] users = this.userGenerator.GetUsers();
                    //foreach (int user in users)
                    //{
                    if (this.userGenerator.NumberOfUsers > 0) //this line prevents multiple users
                    {
                        int user = users[0];

                        if (this.shouldPrintID)
                        {
                            KinectPoint3D com = this.userGenerator.GetCoM(user);
                            com = this.depth.ConvertRealWorldToProjective(com);

                            string label = "";
                            if (!this.shouldPrintState)
                                label += user;
                            else if (this.skeletonCapbility.IsTracking(user))
                                label += user + " - CoM";
                            else if (this.skeletonCapbility.IsCalibrating(user))
                                label += user + " - Kalibreren...";
                            else
                                label += user + " - Zoeken naar persoon";

                            g.DrawString(label, new Font("Arial", 6), new SolidBrush(anticolors[user % ncolors]), (float)com.X, (float)com.Y);

                        }
                        if (this.shouldDrawSkeleton && this.skeletonCapbility.IsTracking(user))
                            DrawSkeleton(g, anticolors[user % ncolors], user);
                    }
                    g.Dispose();
                }
                this.Invalidate();
            }
        }

        #endregion

        #region GENERAL METHODS
        const double widthFactor = 1.04873477;
        const double heightFactor = 1.10875;
        private void resizePanel()
        {
            //resize
            int w = (int)(widthFactor * this.ClientSize.Width);
            int h = (int)(heightFactor * this.ClientSize.Height);
            //center
            Point p = new Point(
            this.ClientSize.Width / 2 - pnlView.Size.Width / 2,
            this.ClientSize.Height / 2 - pnlView.Size.Height / 2);
            pnlView.Anchor = AnchorStyles.None;
            //do it
            pnlView.SetBounds(p.X, p.Y, w, h);
        }
        private void startMeting()
        {
            if (blFoundKinect)
            {
                kd = new KinectData(1800);

                //test if other classes aren't messing with data
                if (ked == null && krd == null)
                {
                    blMeasuring = true;
                    //set menu
                    UpdateMenu();
                    stopMetingToolStripMenuItem.Enabled = true;
                    metingOpslaanAlsToolStripMenuItem.Enabled = true;
                    startMetingToolStripMenuItem.Enabled = false;
                    toolStripStatusLabel1.Text = "De meting is gestart";
                }
                else
                    MessageBox.Show("Er wordt nog data ingelezen of geexporteerd", "Mededeling!", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
            }
        }
        private void stopMeting()
        {
            if (blFoundKinect)
            {
                blMeasuring = false;
                toolStripStatusLabel1.Text = "De meting is gestopt";
                toolStripStatusLabel2.Text = "";

                //menustrip 
                stopMetingToolStripMenuItem.Enabled = false;
                slaMetingOpToolStripMenuItem.Enabled = true;
                startMetingToolStripMenuItem.Enabled = true;
                optimaliseerMetingToolStripMenuItem.Enabled = true;
                slaOptimalisatieOpToolStripMenuItem.Enabled = true;
            }
        }
        private void slaMetingOp()
        {
            if (kd.DataPresent)
            {
                ked = new KinectExportData(kd);
                ked.SaveFile();
                ked.ExportRawData(blUseMarker);
                toolStripStatusLabel1.Text = "De meting is opgeslagen: " + ked.FileLocationAndFileName;
            }
            startMetingToolStripMenuItem.Enabled = true;
            ked = null;
        }
        private void updateSmoothFactor(float smooth)
        {
            if (smooth >= 1.0F)
                smooth = 1.0F;
            else if (smooth <= 0.0F)
                smooth = 0.0F;
            this.skeletonCapbility.SetSmoothing(smooth);
            toolStripStatusLabel1.Text = "Smooth factor = " + smooth.ToString();
        }
        #endregion

        #region BACKGROUNDWORKERS
        private void bgwDataHandling_DoWork(object sender, DoWorkEventArgs e)
        {
            //kd.AddDataToKinectData((Dictionary<SkeletonJoint, SkeletonJointPosition>)dict.Copy());
            if (!gebruikRealworldCoordinatenToolStripMenuItem.Checked)
            {
                if (blUseMarker)
                {
                    kd.AddDataToKinectData(dict, blMarkerPressed);
                    blMarkerPressed = false;
                }
                else
                    kd.AddDataToKinectData(dict);
            }
            else
            {
                if (blUseMarker)
                {
                    kd.AddDataToKinectData(dictForSaving, blMarkerPressed);
                    blMarkerPressed = false;
                }
                else
                    kd.AddDataToKinectData(dictForSaving);
            }
        }
        private void bgwDataHandling_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        { }
        private void bgwDataHandling_ProgressChanged(object sender, ProgressChangedEventArgs e)
        {

        }
        private void bgwOptimaliseren_DoWork(object sender, DoWorkEventArgs e)
        {
            KinectData kinectData = kd.Copy();

            toolStripStatusLabel1.Text = "Data wordt geoptimaliseerd";
            if (kinectData.DataPresent)
            {
                KinectOptimiseData kop = new KinectOptimiseData(kinectData, depth, bgwOptimaliseren);
                kinectData = kop.OptimizeJointData();
            }
            else
                messageBox("Er is geen data om te optimaliseren");
            toolStripStatusLabel1.Text = "Data is geoptimaliseerd en kan worden bekeken/opgeslagen";

            kd = kinectData;
        }
        private void bgwOptimaliseren_ProgressChanged(object sender, ProgressChangedEventArgs e)
        {
            toolStripProgressBar1.Value = e.ProgressPercentage;
            statusStrip1.Text = (string)e.UserState;
        }
        private void bgwOptimaliseren_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            UpdateMenu();
        }
        #endregion

        #region MENU_HANDLING
        private void metingOpslaanAlsToolStripMenuItem_Click(object sender, EventArgs e)
        {
            ked = new KinectExportData(kd);
            ked.SaveFile();
            ked.ExportRawData(blUseMarker);
            ked = null;
        }
        private void slaSkeletKalibratieDatOpToolStripMenuItem_Click(object sender, EventArgs e)
        {
            FileHandling fh = new FileHandling();
            fh.SaveFile();
            if (fh.FileLocationAndFileName != "")
                this.skeletonCapbility.SaveCalibrationDataToFile(1, fh.FileLocationAndFileName);
        }
        private void openSkeletKalibratieToolStripMenuItem_Click(object sender, EventArgs e)
        {
            FileHandling fh = new FileHandling();
            fh.OpenFile("bin");
            try
            {
                this.skeletonCapbility.LoadCalibrationDataFromFile(1, fh.FileLocationAndFileName);
                toolStripStatusLabel1.Text = "Succesvol skelet kalibratie data geladen!";
            }
            catch (Exception)
            {
                toolStripStatusLabel1.Text = "skelet kalibratie data niet geladen!";
            }

        }
        private void laatHoekenZienToolStripMenuItem_Click(object sender, EventArgs e)
        {
            laatHoekenZiendegToolStripMenuItem.Checked = !laatHoekenZiendegToolStripMenuItem.Checked;
        }
        private void rekalibreerSkeletToolStripMenuItem_Click(object sender, EventArgs e)
        {

        }
        private void muisMeetModusToolStripMenuItem_Click(object sender, EventArgs e)
        {
            muisMeetmodusToolStripMenuItem.Checked = !muisMeetmodusToolStripMenuItem.Checked;
        }
        private void optimaliseerLaatsteMetingToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (kd.NumberOfOptimisedDataSets != 0)
            {
                optimaliseerMetingToolStripMenuItem.Checked = !optimaliseerMetingToolStripMenuItem.Checked;
                bgwOptimaliseren.RunWorkerAsync();
            }
            else
                messageBox("Geef in het menu -Gewrichten en posities- aan wat moet worden geoptimaliseerd");
        }

        private void gebruikRealworldCoordinatesToolStripMenuItem_Click(object sender, EventArgs e)
        {
            gebruikRealworldCoordinatenToolStripMenuItem.Checked = !gebruikRealworldCoordinatenToolStripMenuItem.Checked;
        }
        private void frmMain_Resize(object sender, EventArgs e)
        {
            resizePanel();
        }
        private void frmMain_SizeChanged(object sender, EventArgs e)
        {
            resizePanel();
        }
        private void muisMeetmodusToolStripMenuItem_Click_1(object sender, EventArgs e)
        {
            muisMeetmodusToolStripMenuItem.Checked = !muisMeetmodusToolStripMenuItem.Checked;
        }
        private void openMetingToolStripMenuItem_Click_1(object sender, EventArgs e)
        {
            krd = new KinectReadData();
            krd.Initialize();
            kd = krd.GetKinectData;

            if (krd.ReadWithSucces)
            {
                toolStripStatusLabel1.Text = "Het bestand is ingelezen";
                toolStripProgressBar1.Value = 100;
                optimaliseerMetingToolStripMenuItem.Checked = false;
                optimaliseerMetingToolStripMenuItem.Enabled = false;
            }
            else
            {
                toolStripStatusLabel1.Text = "Geen bestand ingelezen!";
                toolStripProgressBar1.Value = 0;
            }
            UpdateMenu();
            krd = null;
        }
        private void gebruikRealworldCoordinatenToolStripMenuItem_Click(object sender, EventArgs e)
        {
            gebruikRealworldCoordinatenToolStripMenuItem.Checked = !gebruikRealworldCoordinatenToolStripMenuItem.Checked;
        }
        private void startMetingToolStripMenuItem_Click_1(object sender, EventArgs e)
        {
            startMeting();
        }
        private void stopMetingToolStripMenuItem_Click(object sender, EventArgs e)
        {
            stopMeting();
        }
        private void slaMetingOpToolStripMenuItem_Click(object sender, EventArgs e)
        {
            slaMetingOp();
        }
        private void laatLengtesZienmmToolStripMenuItem_Click(object sender, EventArgs e)
        {
            laatLengtesZienmmToolStripMenuItem.Checked = !laatLengtesZienmmToolStripMenuItem.Checked;
        }
        private void laatHoekenZiendegToolStripMenuItem_Click(object sender, EventArgs e)
        {
            laatHoekenZiendegToolStripMenuItem.Checked = !laatHoekenZiendegToolStripMenuItem.Checked;
        }
        private void skeletSmoothFactorToolStripMenuItem_Click(object sender, EventArgs e)
        {

        }
        private void laatDataZienToolStripMenuItem_Click(object sender, EventArgs e)
        {
            ked = new KinectExportData(kd);

            //convert to string
            kd = ked.MakeTxtFromRawData(kd);


            if (kd.StringDataPresent)
            {
                frmShowData frmShowData = new frmShowData(kd, "Ruwe data");
                frmShowData.Show();
            }
            else
                messageBox("Geen data gevonden");
            ked = null;
        }
        private void laatGeoptimaliseerdeDataZienToolStripMenuItem_Click(object sender, EventArgs e)
        {
            KinectData tempKd = kd.Copy();
            ked = new KinectExportData();
            tempKd = ked.MakeTxtFromOptimisedData(tempKd);

            if (tempKd.StringDataPresent)
            {
                frmShowData frmShowOData = new frmShowData(tempKd, "Geoptimaliseerde Data");
                frmShowOData.Show();
            }
            else
                messageBox("Geen geoptimaliseerde data gevonden");
            ked = null;
            kd = tempKd;
        }

        private void allesSelecterenToolStripMenuItem_Click_1(object sender, EventArgs e)
        {
            allesSelecterenToolStripMenuItem.Checked = !allesSelecterenToolStripMenuItem.Checked;

            linkerElleboogToolStripMenuItem.Checked = allesSelecterenToolStripMenuItem.Checked;
            linkerKnieToolStripMenuItem.Checked = allesSelecterenToolStripMenuItem.Checked;
            linkerSchouderToolStripMenuItem.Checked = allesSelecterenToolStripMenuItem.Checked;
            rechterElleboogToolStripMenuItem.Checked = allesSelecterenToolStripMenuItem.Checked;
            rechterKnieToolStripMenuItem.Checked = allesSelecterenToolStripMenuItem.Checked;
            rechterSchouderToolStripMenuItem.Checked = allesSelecterenToolStripMenuItem.Checked;

            allesRechtsToolStripMenuItem.Checked = allesSelecterenToolStripMenuItem.Checked;
            allesLinksToolStripMenuItem.Checked = allesSelecterenToolStripMenuItem.Checked;

            UpdateMenu();
        }
        private void allesLinksToolStripMenuItem_Click_1(object sender, EventArgs e)
        {
            allesLinksToolStripMenuItem.Checked = !allesLinksToolStripMenuItem.Checked;
            linkerElleboogToolStripMenuItem.Checked = allesLinksToolStripMenuItem.Checked;
            linkerKnieToolStripMenuItem.Checked = allesLinksToolStripMenuItem.Checked;
            linkerSchouderToolStripMenuItem.Checked = allesLinksToolStripMenuItem.Checked;

            UpdateMenu();
        }
        private void allesRechtsToolStripMenuItem_Click_1(object sender, EventArgs e)
        {
            allesRechtsToolStripMenuItem.Checked = !allesRechtsToolStripMenuItem.Checked;
            rechterElleboogToolStripMenuItem.Checked = allesRechtsToolStripMenuItem.Checked;
            rechterKnieToolStripMenuItem.Checked = allesRechtsToolStripMenuItem.Checked;
            rechterSchouderToolStripMenuItem.Checked = allesRechtsToolStripMenuItem.Checked;

            UpdateMenu();
        }
        private void linkerSchouderToolStripMenuItem_Click_1(object sender, EventArgs e)
        {
            linkerSchouderToolStripMenuItem.Checked = !linkerSchouderToolStripMenuItem.Checked;
            UpdateMenu();
        }
        private void linkerElleboogToolStripMenuItem_Click_1(object sender, EventArgs e)
        {
            linkerElleboogToolStripMenuItem.Checked = !linkerElleboogToolStripMenuItem.Checked;
            UpdateMenu();
        }
        private void linkerKnieToolStripMenuItem_Click_1(object sender, EventArgs e)
        {
            linkerKnieToolStripMenuItem.Checked = !linkerKnieToolStripMenuItem.Checked;
            UpdateMenu();
        }
        private void rechterSchouderToolStripMenuItem_Click_1(object sender, EventArgs e)
        {
            rechterSchouderToolStripMenuItem.Checked = !rechterSchouderToolStripMenuItem.Checked;
            UpdateMenu();
        }
        private void rechterElleboogToolStripMenuItem_Click_1(object sender, EventArgs e)
        {
            rechterElleboogToolStripMenuItem.Checked = !rechterElleboogToolStripMenuItem.Checked;
            UpdateMenu();
        }
        private void rechterKnieToolStripMenuItem_Click_1(object sender, EventArgs e)
        {
            rechterKnieToolStripMenuItem.Checked = !rechterKnieToolStripMenuItem.Checked;
            UpdateMenu();
        }
        private void UpdateMenu()
        {
            bool blDepth = this.depth == null;
            bool blData = kd == null;

            if (blDepth && blData)
            {
                gewrichtenPositiesToolStripMenuItem.Enabled = false;
            }

            if (blDepth) //no Kinect
            {
                beeldToolStripMenuItem.Enabled = false;
                metenToolStripMenuItem.Enabled = false;
                metingOpslaanAlsToolStripMenuItem.Enabled = false;
                skeletSmoothFactorToolStripMenuItem.Enabled = false;
                slaSkeletKalibratieOpToolStripMenuItem.Enabled = false;
                rekalibreerSkeletToolStripMenuItem.Enabled = false;
            }
            else
            {
                beeldToolStripMenuItem.Enabled = true;
                laatLengtesZienmmToolStripMenuItem.Enabled = true;
                laatHoekenZiendegToolStripMenuItem.Enabled = true;

                metenToolStripMenuItem.Enabled = true;
                metingOpslaanAlsToolStripMenuItem.Enabled = true;
                skeletSmoothFactorToolStripMenuItem.Enabled = true;
                slaSkeletKalibratieOpToolStripMenuItem.Enabled = true;
                rekalibreerSkeletToolStripMenuItem.Enabled = true;
            }

            if (blData) //no data
            {
                optimaliseerToolStripMenuItem.Enabled = false;
                exporteerToolStripMenuItem.Enabled = false;
                toolStripStatusLabel1.Text = "Er is geen data (ingeladen)!";
            }
            else
            {
                beeldToolStripMenuItem.Enabled = true;

                gewrichtenPositiesToolStripMenuItem.Enabled = true;
                exporteerToolStripMenuItem.Enabled = true;
                optimaliseerMetingToolStripMenuItem.Enabled = true;
                optimaliseerToolStripMenuItem.Enabled = true;
                laatDataZienToolStripMenuItem.Enabled = true;
                if (kd.OptimisedDataPresent)
                    laatGeoptimaliseerdeDataZienToolStripMenuItem.Enabled = true;
                else
                    laatGeoptimaliseerdeDataZienToolStripMenuItem.Enabled = false;

                //lijst aanpassen a.h.v. de checked
                kd.SkeletonJointsToBeOptimised.Clear();
                kd.SkeletonJointsSelected.Clear();
                if (linkerElleboogToolStripMenuItem.Checked)
                    addNeededSkeletonJoints(SkeletonJoint.LeftElbow);
                if (linkerKnieToolStripMenuItem.Checked)
                    addNeededSkeletonJoints(SkeletonJoint.LeftKnee);
                if (linkerSchouderToolStripMenuItem.Checked)
                    addNeededSkeletonJoints(SkeletonJoint.LeftShoulder);
                if (rechterElleboogToolStripMenuItem.Checked)
                    addNeededSkeletonJoints(SkeletonJoint.RightElbow);
                if (rechterKnieToolStripMenuItem.Checked)
                    addNeededSkeletonJoints(SkeletonJoint.RightKnee);
                if (rechterSchouderToolStripMenuItem.Checked)
                    addNeededSkeletonJoints(SkeletonJoint.RightShoulder);
            }
        }

        private void addNeededSkeletonJoints(SkeletonJoint sk)
        {
            kd.SkeletonJointsToBeOptimised.Add(sk);
            kd.SkeletonJointsSelected.Add(kd.GetJoints(sk)[0]);
            kd.SkeletonJointsSelected.Add(kd.GetJoints(sk)[1]);
            kd.SkeletonJointsSelected.Add(kd.GetJoints(sk)[2]);
        }

        private void slaOptimalisatieVanMetingOpToolStripMenuItem_Click_1(object sender, EventArgs e)
        {
            ked = new KinectExportData(kd);
            ked.SaveFile();
            ked.ExportOptimisedData(kd.WitMarkerData);
            ked = null;
        }
        private void gebruikMarkerToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (!blMeasuring) //can't be measuring
                blUseMarker = !blUseMarker;
        }
        private void frmMain_MouseClick(object sender, MouseEventArgs e)
        {
            if (muisMeetmodusToolStripMenuItem.Checked)
            {
                blUseMarker = true; //meten met muis = markermodus aan

                if (e.Button == System.Windows.Forms.MouseButtons.Left)
                {
                    if (blMeasuring)
                        stopMeting();
                    else
                        startMeting();
                }
                if (e.Button == System.Windows.Forms.MouseButtons.Right)
                {
                    markerPressed();
                }
            }
        }

        private void markerPressed()
        {
            blMarkerPressed = true;
            if (toolStripStatusLabel2.Text == strTxtMarker)
                toolStripStatusLabel2.Text = "  " + strTxtMarker;
            else
                toolStripStatusLabel2.Text = strTxtMarker;
        }
        private void ruweDataToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (kd != null && kd.DataPresent)
            {
                if (kd.SkeletonJointsToBeOptimised.Count != 0)
                {
                    ked = new KinectExportData(kd);
                    ked.SaveFile();
                    ked.ExportSelectedData(kd.WitMarkerData);
                    ked = null;
                }
                else
                    messageBox("Geen gewrichten geselecteerd!");
            }
        }
        private void hoekdataToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (kd != null && kd.DataPresent)
            {
                if (kd.SkeletonJointsToBeOptimised.Count != 0)
                {
                    ked = new KinectExportData(kd, kbc);
                    ked.SaveFile();
                    ked.ExportAngleData();
                    ked = null;
                }
                else
                    messageBox("Geen gewrichten geselecteerd!");
            }
        }
        private void hoeksnelhedenToolStripMenuItem_Click(object sender, EventArgs e)
        {
            notCompleted();
        }
        private void snelhedenToolStripMenuItem_Click(object sender, EventArgs e)
        {
            notCompleted();
        }
        private void notCompleted()
        {
            messageBox("Deze functionaliteit is helaas nog niet beschikbaar.... :(");
        }
        private void messageBox(string text)
        {
            MessageBox.Show(text, "Mededeling", MessageBoxButtons.OK, MessageBoxIcon.Information);
        }

        private void skeletSmoothFactorToolStripMenuItem_Click_2(object sender, EventArgs e)
        {

        }
        private void rekalibreerSkeletToolStripMenuItem_Click_2(object sender, EventArgs e)
        {
            try // in case no user is defined
            {
                this.skeletonCapbility.StopTracking(1);
                this.skeletonCapbility.Reset(1);
                this.skeletonCapbility.RequestCalibration(1, true);
            }
            catch (Exception)
            {
            }
        }
        private void resetToolStripMenuItem_Click(object sender, EventArgs e)
        {
            setupAll();
        }
        private void markerToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (blUseMarker)
            {
                markerPressed();
            }
        }
        private void gebruikRealworldCoordinatenToolStripMenuItem_Click_1(object sender, EventArgs e)
        {
            gebruikRealworldCoordinatenToolStripMenuItem.Checked = !gebruikRealworldCoordinatenToolStripMenuItem.Checked;
        }
        private void definitiesGewrichtenToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (!hlp.Visible)
                hlp.Show();
        }
        

        private void muisMeetmodusToolStripMenuItem1_Click(object sender, EventArgs e)
        {
            if(!mmd.Visible)
             mmd.Show();
        }
        
        private void LaatCoordinatenHandenZien_Click(object sender, EventArgs e)
        {
            LaatCoordinatenHandenZien.Checked = !LaatCoordinatenHandenZien.Checked;
        }
#endregion

       

    }
}
